## 3.8. Virtual Hosts

On site.twocopy (see Section 3.9, "Two Copies of Apache", later in this chapter) we run two different versions of Apache, each serving a different URL. It would be rather unusual to do this in real life. It is more common to run a number of virtual Apaches that steer incoming requests on different URLs -- usually with the same IP address -- to different sets of documents. These might well be home pages for members of your organization or your clients.

In the first edition of this book we showed how to do this for Apache 1.2 and HTTP/1.0. The result was rather clumsy, with a main host and a virtual host, but it coped with HTTP/1.0 clients. However, the setup can now be done much more neatly with the `NameVirtualHost` directive. The possible combinations of IP-based and name-based hosts can become quite complex. A full explanation with examples and the underlying theology can be found at http://www.apache.org/docs/vhosts but it has to be said that several of the possible permutations are unlikely to be very useful in practice.

### 3.8.1. Name-Based Virtual Hosts

This is by far the preferred method of managing virtual hosts, taking advantage of the ability of HTTP/1.1-compliant browsers to send the name of the site they want to access. At .../site.virtual/Name-based we have www.butterthlies.com and sales. butterthlies.com on 192.168.123.2. Of course, these sites must be registered on the Web (or if you are dummying the setup as we did, included in /etc/hosts). The Config file is as follows:

>     User webuser
>     Group webgroup

>     NameVirtualHost 192.168.123.2

>     <VirtualHost www.butterthlies.com>
>     ServerAdmin sales@butterthlies.com
>     DocumentRoot /usr/www/site.virtual/htdocs/customers
>     ServerName www.butterthlies.com
>     ErrorLog /usr/www/site.virtual/name-based/logs/error_log
>     TransferLog /usr/www/site.virtual/name-based/logs/access_log
>     </VirtualHost>

>     <VirtualHost sales.butterthlies.com>
>     ServerAdmin sales@butterthlies.com
>     DocumentRoot /usr/www/site.virtual/htdocs/salesmen
>     ServerName sales.butterthlies.com
>     ErrorLog /usr/www/site.virtual/name-based/logs/error_log
>     TransferLog /usr/www/site.virtual/name-based/logs/access_log
>     </VirtualHost>

The key directive is `NameVirtualHost` , which tells Apache that requests to that IP number will be subdivided by name. It might seem that the `ServerName` directives play a crucial part, but they just provide a name for Apache to return to the client. The `<VirtualHost>` sections now are identified by the name of the site we want them to serve. If this directive were left out, Apache would issue a helpful warning that www.butterthlies.com and sales.butterthlies.com were overlapping (i.e., rival interpretations of the same IP number) and that perhaps we needed a `NameVirtualHost` directive. Which indeed we would.

The virtual sites can all share log files, as shown in the given Config file, or they can use separate ones.

### 3.8.1.1. NameVirtualHost

>     NameVirtualHost address[:port]
>     Server config

`NameVirtualHost` allows you to specify the IP addresses of your name-based virtual hosts. Optionally, you can add a port number. The IP address has to match with the IP address at the top of a <`VirtualHost>` block, which must include a `ServerName` directive followed by the registered name. The effect is that when Apache receives a request addressed to a named host, it scans the `<VirtualHost>` blocks having the same IP number that was declared with a `NameVirtualHost` directive to find one that includes the requested `ServerName`. Conversely, if you have not used `NameVirtualHost`, Apache looks for a `<VirtualHost>` block with the correct IP address and uses the `ServerName` in the reply. One use of this is to prevent people from getting to hosts blocked by the firewall by using the IP of an open host and the name of a blocked one.

### 3.8.2. IP-Based Virtual Hosts

In the authors' experience, most of the Web still uses IP-based hosting, because although almost all clients use browsers that support HTTP/1.1, there is still a tiny proportion that doesn't, and who wants to lose business unnecessarily? However, the Web is running out of numbers, and sooner or later, people will have to move to name-based hosting.

This is how to configure Apache to do IP-based virtual hosting. The Config file is:

>     User webuser
>     Group webgroup

>     <VirtualHost 192.168.123.2>
>     ServerName www.butterthlies.com
>     ServerAdmin sales@butterthlies.com
>     DocumentRoot /usr/www/site.virtual/htdocs/customers
>     ErrorLog /usr/www/site.virtual/IP-based/logs/error_log
>     TransferLog /usr/www/site.virtual/IP-based/logs/access_log
>     </VirtualHost>

>     <VirtualHost 192.168.123.3>
>     ServerName sales.butterthlies-IP.com
>     ServerAdmin sales@butterthlies.com
>     DocumentRoot /usr/www/site.virtual/htdocs/salesmen
>     ServerName sales.butterthlies.com
>     ErrorLog /usr/www/site.virtual/IP-based/logs/error_log
>     TransferLog /usr/www/site.virtual/IP-based/logs/access_log
>     </VirtualHost>

This responds nicely to requests to http://www.butterthlies.com and http://sales-IP.butterthlies.com. The way our machine was set up, it also served up the customers' page to a request on http://www.sales.com -- which is to be expected since they share a common IP number.

### 3.8.3. Mixed Name/IP-Based Virtual Hosts

You can, of course, mix the two techniques. `<VirtualHost>` blocks that have been N`ameVirtualHost`'ed will respond to requests to named servers; others will respond to requests to the appropriate IP numbers:

>     User webuser
>     Group webgroup

>     NameVirtualHost 192.168.123.2

>     <VirtualHost www.butterthlies.com>
>     ServerAdmin sales@butterthlies.com
>     DocumentRoot /usr/www/site.virtual/htdocs/customers
>     ErrorLog /usr/www/site.virtual/IP-based/logs/error_log
>     TransferLog /usr/www/site.virtual/IP-based/logs/access_log
>     </VirtualHost>

>     <VirtualHost sales.butterthlies.com>
>     ServerAdmin sales@butterthlies.com
>     DocumentRoot /usr/www/site.virtual/htdocs/salesmen
>     ServerName sales.butterthlies.com
>     ErrorLog /usr/www/site.virtual/IP-based/logs/error_log
>     TransferLog /usr/www/site.virtual/IP-based/logs/access_log
>     </VirtualHost>

>     <VirtualHost 192.168.123.3>
>     ServerAdmin sales@butterthlies.com
>     DocumentRoot /usr/www/site.virtual/htdocs/salesmen
>     ServerName sales.butterthlies.com
>     ErrorLog /usr/www/site.virtual/IP-based/logs/error_log
>     TransferLog /usr/www/site.virtual/IP-based/logs/access_log
>     </VirtualHost>

The two named sites are dealt with by the `NameVirtualHost` directive, whereas requests to sales-IP.butterthlies.com, which we have set up to be 192.168.123.3, are dealt with by the third `<VirtualHost>` block.

### 3.8.4. Port-Based Virtual Hosting

Port-based virtual hosting follows on from IP-based hosting. The main advantage of this technique is that it makes it possible for a webmaster to test a lot of sites using only one IP address/hostname, or, in a pinch, host a large number of sites without using name-based hosts and without using lots of IP numbers. Unfortunately, most people don't like their web server having a funny port number.

>     User webuser
>     Group webgroup
>     Listen 80
>     Listen 8080
>     <VirtualHost 192.168.123.2:80>
>     ServerName www.butterthlies.com
>     ServerAdmin sales@butterthlies.com
>     DocumentRoot /usr/www/site.virtual/htdocs/customers
>     ErrorLog /usr/www/site.virtual/IP-based/logs/error_log
>     TransferLog /usr/www/site.virtual/IP-based/logs/access_log
>     </VirtualHost>

>     <VirtualHost 192.168.123.2:8080>
>     ServerName sales-IP.butterthlies.com
>     ServerAdmin sales@butterthlies.com
>     DocumentRoot /usr/www/site.virtual/htdocs/salesmen
>     ServerName sales.butterthlies.com
>     ErrorLog /usr/www/site.virtual/IP-based/logs/error_log
>     TransferLog /usr/www/site.virtual/IP-based/logs/access_log
>     </VirtualHost>

The `Listen` directives tell Apache to watch ports 80 and 8080. If you set Apache going and access http://www.butterthlies.com, you arrive on port 80, the default, and see the customers' site; if you access http://www.butterthlies.com:8080, you get the salespeople's site.

Copyright © 2001 O'Reilly & Associates. All rights reserved.